<?php

namespace App\Services;

use App\Exceptions\WalletException;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Arr;

class WalletService
{
    private $apiHost;
    private $apiKey;
    private $apiSecret;

    /** * WalletService constructor. */
    public function __construct()
    {
        $this->apiHost = config('services.wallet.host');
        $this->apiKey = config('services.wallet.key');
        $this->apiSecret = config('services.wallet.secret');
    }

    /** 开通钱包,返回钱包地址 */
    public function openWallet($mobile)
    {
        return $this->doGet('/sc/openWallet', [
            'mobile' => $mobile,
        ]);
    }

    /** 查询产品存证信息 */
    public function productEvidence($publicHash)
    {
        return $this->doGet('/sc/evidenceInfo', [
            'hash' => $publicHash,
            'tokenId' => '',
            'hashType' => 'p',
        ]);
    }

    /** 查询token交易存证信息 */
    public function tokenTransEvidence($tokenId, $transHash)
    {
        return $this->doGet('/sc/evidenceInfo', [
            'hash' => $transHash,
            'tokenId' => $tokenId,
            'hashType' => 't',
        ]);
    }

    /** 查询资产交易记录 */
    public function tokenTransList($contractAddress, $tokenId)
    {
        return $this->doGet('/sc/tokenTransList', [
            'commodity' => $contractAddress,
            'tokenId' => $tokenId,
        ]);
    }

    /** 资产转移 */
    public function transfer($fromMobile, $contractAddress, $tokenIds, $toAddress)
    {
        $resp = $this->doPost(
            '/sc/bthTransfer',
            ['txid' => uniqid()],
            [
                'name' => '',
                'mobile' => $fromMobile,
                'address' => $toAddress,
                'commodity' => $contractAddress,
                'tokenIds' => $tokenIds,
            ]
        );
        $successList = Arr::get($resp, 'successList', []);
        $result = [];
        foreach ($successList as $item) {
            $result[$item['tokenId']] = $item['transHash'];
        }

        return $result;
    }

    /** 查询我的资产 */
    public function assetList($walletAddress)
    {
        return $this->doGet('/sc/assetsList', [
            'walletAddress' => $walletAddress,
        ]);
    }

    private function doGet($path, $queryParams)
    {
        $queryParams['sign'] = $this->getSign($queryParams);
        $url = sprintf(
            '%s%s?appkey=%s&%s',
            $this->apiHost,
            $path,
            $this->apiKey,
            http_build_query($queryParams)
        );
        \Log::channel('wallet')->info('GET:' . $url);

        return $this->parseResponse(\Http::get($url));
    }

    private function doPost($path, $queryParams, $data)
    {
        $queryParams['sign'] = $this->getSign($queryParams);
        $url = sprintf(
            '%s%s?appkey=%s&%s',
            $this->apiHost,
            $path,
            $this->apiKey,
            http_build_query($queryParams)
        );
        \Log::channel('wallet')->info('POST:' . $url, $data);
        $resp = \Http::asJson()->post($url, $data);

        return $this->parseResponse($resp);
    }

    /** 获取接口签名 */
    private function getSign($params)
    {
        return md5($this->apiKey . implode('', $params) . $this->apiSecret);
    }

    /** 返回值处理 */
    private function parseResponse(Response $response)
    {
        \Log::channel('wallet')->info('Response:' . $response->body());
        $data = $response->json();
        $code = Arr::get($data, 'code');
        if (200 == $code) {
            return Arr::get($data, 'content', []);
        }
        $msg = Arr::get($data, 'message', '未知错误');
        $content = Arr::get($data, 'content', $msg);
        if (is_array($content)) {
            $content = Arr::get($content, 'error.errLog', $msg);
        }

        throw new WalletException($content);
    }
}
